package edu.neumont.pro180._2009_q2.network;

import java.util.ArrayList;
import java.util.Random;

import edu.neumont.pro180._2009_q2.GamePieceMove;
import edu.neumont.pro180._2009_q2.Player;
import edu.neumont.pro180._2009_q2.Square;
import edu.neumont.pro180._2009_q2.interfaces.IGamePiece;

public class AI extends Player {
	private NetworkGame game;
	private ArrayList<Square> occupiedSquares;
	private ArrayList<Square> moveSquares;
	private ArrayList<GamePieceMove> possibleMoves;

	public AI() {
		moveSquares = new ArrayList<Square>();
		occupiedSquares = new ArrayList<Square>();
		possibleMoves = new ArrayList<GamePieceMove>();
	}

	public AI(NetworkGame game) {
		this();
		this.game = game;
	}

	@SuppressWarnings("unused")
	private void update() {
		// TODO: update the board squares w/ offensive and defensive values
		// this is theory of how the movements set should work.
		// done at 12:30 so to tiered to keep thinking clearly but i got the
		// basics covered
		// any more basic ideas would be appreciated at this point :)
		// every thing is commented out to ensure I don't screw anything up

		// also i added more fields for some of the the defense logic and
		// possible offense? or something inside of the square class adn made
		// getters setters and adders???.
		// but one way or another for the logic me and Ernesto came up with i
		// think thats what well need but
		// i gues well soon find out ??
		for (Square s : moveSquares) {
			if (s.hasGamePiece() && s.getGamePiece().getPlayer() != this) {
				// need to figure out how to determine between white and black
				// squares
				// s.addDefenciveWhiteValue();
				// need to determine how to compensate for pawn attack versus
				// movement
				// s.addOffenceWhiteValue();
			} else if (s.hasGamePiece() && s.getGamePiece().getPlayer() == this) {
				// need to figure out how to determine between white and black
				// squares
				// s.addDefenciveBlackValue();
				// need to determine how to compensate for pawn attack versus
				// movement
				// s.addOffenceBlackValue();
			}
		}

	}

	private ArrayList<Square> getPossibleSquares() {
		ArrayList<Square> moveSquares = new ArrayList<Square>();
		
		for(IGamePiece p : this.getActivePieces()) {
			moveSquares.addAll(p.getPossibleSquares());
		}
		
		return moveSquares;
	}
	
	private ArrayList<Square> getSquaresOccupiedByOpponent(ArrayList<Square> squares) {
		ArrayList<Square> occupiedSquares = new ArrayList<Square>();
		
		for(Square s : squares) {
			if(s.hasGamePiece() && s.getGamePiece().getPlayer() != this) {
				occupiedSquares.add(s);
			}
		}
		
		// sort the squares occupied by the opponent by point value
		for (int i = 0; i < occupiedSquares.size(); i++) {
			for (int j = 0; j < occupiedSquares.size(); j++) {
				if (occupiedSquares.get(i).getGamePiece().getValue() > occupiedSquares
						.get(j).getGamePiece().getValue()) {
					Square temp = occupiedSquares.get(i);
					occupiedSquares.set(i, occupiedSquares.get(j));
					occupiedSquares.set(j, temp);
				}
			}
		}
		
		return occupiedSquares;		
	}
	
	private ArrayList<GamePieceMove> getMoves(ArrayList<Square> occupiedSquares) {
		ArrayList<GamePieceMove> moves = new ArrayList<GamePieceMove>();
		
		// create the list of potential captures
		for (Square s : occupiedSquares) {
			for (IGamePiece p : this.getActivePieces()) {
				if (p.getPossibleSquares().contains(s)) {
					possibleMoves.add(new GamePieceMove(p, s));
				}
			}
		}
		
		return moves;
	}
	
	
	private ArrayList<GamePieceMove> getAcceptableMoves(ArrayList<GamePieceMove> potentialMoves) {
		
		ArrayList<GamePieceMove> acceptableMoves = new ArrayList<GamePieceMove>();
		for (GamePieceMove move : potentialMoves) {
			// execute the move
			this.board.doMove(move);

			// check for check, checkmate, TODO: check for threat against capturing piece
			if(!(this.game.isInCheck(this, this.board)||this.game.isInCheckmate(this, this.board)))
				acceptableMoves.add(move);
			
			// undo the move
			this.board.undoMove(move);
		}
		
		return acceptableMoves;
	}
	
	@Override
	public GamePieceMove getNextMove() {
		// this.update();

		// squares that you can move to
//		for (IGamePiece p : this.getActivePieces()) {
//			moveSquares.addAll((p.getPossibleSquares()));
//		}
		

		// squares you can move to that are occupied by the opponent
//		for (Square s : moveSquares) {
//			if (s.hasGamePiece() && s.getGamePiece().getPlayer() != this) {
//				occupiedSquares.add(s);
//			}
//		}
		
		moveSquares = this.getPossibleSquares();
		occupiedSquares = this.getSquaresOccupiedByOpponent(moveSquares);
		
		if (occupiedSquares.size() == 0) {
			// get the square to move to
			Square move = moveSquares.get(new Random().nextInt(moveSquares
					.size()));

			// get the first piece that can move there
			IGamePiece piece = null;
			for (IGamePiece p : this.getActivePieces()) {
				if (p.getPossibleSquares().contains(move)) {
					piece = p;
					break;
				}
			}

			return piece.getMove(move);
		}

		// create the list of potential captures
//		for (Square s : occupiedSquares) {
//			for (IGamePiece p : this.getActivePieces()) {
//				if (p.getPossibleSquares().contains(s)) {
//					possibleMoves.add(new GamePieceMove(p, s));
//				}
//			}
//		}
		
		possibleMoves = this.getMoves(occupiedSquares);

		// determine which moves are acceptable
//		List<GamePieceMove> acceptableMoves = new ArrayList<GamePieceMove>();
//		for (GamePieceMove move : possibleMoves) {
//			// execute the move
//			this.board.doMove(move);
//
//			// check for check, checkmate, TODO: check for threat against capturing piece
//			if(!(this.game.isInCheck(this, this.board)||this.game.isInCheckmate(this, this.board)))
//				acceptableMoves.add(move);
//			
//			// undo the move
//			this.board.undoMove(move);
//		}
		
		ArrayList<GamePieceMove> acceptableMoves = this.getAcceptableMoves(possibleMoves);
		
		if(acceptableMoves.size() == 0) {
			// get the square to move to
			Square move = moveSquares.get(new Random().nextInt(moveSquares
					.size()));

			// get the first piece that can move there
			IGamePiece piece = null;
			for (IGamePiece p : this.getActivePieces()) {
				if (p.getPossibleSquares().contains(move)) {
					piece = p;
					break;
				}
			}

			return piece.getMove(move);
		} else {
			// select the acceptable moves 
			return acceptableMoves.get(0);
		}

		

	}
}
